package main

import (
	"errors"
	"fmt"
	"sync"
)

// 结合 Mutex 和切片，可以实现简单的线程安全队列

// SafeQueue 一个使用 sync.Mutex 实现的线程安全队列
type SafeQueue struct {
	mu   sync.Mutex
	data []interface{}
}

// Enqueue 将一个元素添加到队列尾部
func (q *SafeQueue) Enqueue(item interface{}) {
	q.mu.Lock()
	defer q.mu.Unlock()
	q.data = append(q.data, item)
}

// Dequeue 从队列头部移除并返回一个元素
// 如果队列为空，返回一个错误
func (q *SafeQueue) Dequeue() (interface{}, error) {
	q.mu.Lock()
	defer q.mu.Unlock()

	if len(q.data) == 0 {
		return nil, errors.New("队列已空")
	}

	item := q.data[0]
	// 从切片中删除第一个元素。
	// 注意：这会导致切片中后续元素的内存拷贝，在元素数量很大时效率不高。
	// 生产环境的高性能队列会使用更复杂的数据结构，如环形缓冲区。
	q.data = q.data[1:]

	return item, nil
}

// Peek 获取队首元素，但不移除它
// 如果队列为空，返回一个错误
func (q *SafeQueue) Peek() (interface{}, error) {
	q.mu.Lock()
	defer q.mu.Unlock()

	if len(q.data) == 0 {
		return nil, errors.New("队列已空")
	}

	return q.data[0], nil
}

// Len 获取队列当前的长度
func (q *SafeQueue) Len() int {
	q.mu.Lock()
	defer q.mu.Unlock()
	return len(q.data)
}

// IsEmpty 判断队列是否为空
func (q *SafeQueue) IsEmpty() bool {
	// 直接复用 Len() 方法，保证逻辑一致性
	return q.Len() == 0
}

func main() {
	queue := &SafeQueue{}

	// 入队
	queue.Enqueue("任务1")
	queue.Enqueue("任务2")
	queue.Enqueue("任务3")

	fmt.Printf("队列长度: %d\n", queue.Len()) // 输出: 队列长度: 3

	// 查看队首
	item, err := queue.Peek()
	if err == nil {
		fmt.Printf("队首元素: %s\n", item) // 输出: 队首元素: 任务1
	}

	// 出队
	for !queue.IsEmpty() {
		item, err := queue.Dequeue()
		if err == nil {
			fmt.Printf("出队成功:处理任务: %s\n", item)
		}
	}

	// 尝试从空队列中出队
	item, err = queue.Dequeue()
	if err != nil {
		fmt.Println("出队失败:", err) // 输出: 出队失败: 队列已空
	}
}
